package com.ai.module.user.service.impl;


import com.ai.module.chat.common.base.ThreadLocalContext;
import com.ai.module.chat.common.constant.StringConstant;
import com.ai.module.chat.common.domain.vo.RiskReason;
import com.ai.module.chat.config.properties.UserInfoProperty;
import com.ai.module.websocket.server.WebSocketController;
import com.ai.module.business.domain.vo.UserMessage;
import com.ai.module.business.enu.Source;
import com.ai.module.business.service.BannerRecordService;
import com.ai.module.business.service.MemberCenterService;
import com.ai.module.user.domain.entity.ChatContentEntity;
import com.ai.module.user.domain.entity.UserImageEntity;
import com.ai.module.user.domain.entity.UserRobotEntity;
import com.ai.module.user.domain.req.UserTalkReq;
import com.ai.module.user.domain.vo.UserLoginInfo;
import com.ai.module.user.domain.vo.UserTimeVo;
import com.ai.module.user.enu.PointSource;
import com.ai.module.user.mapper.ChatContentMapper;
import com.ai.module.user.mapper.UserImageMapper;
import com.ai.module.user.service.ChatService;
import com.ai.module.user.service.UserImageAnalyzeService;
import com.ai.module.user.service.UserRobotService;
import com.ai.module.chat.util.DateUtils;
import com.ai.module.chat.util.FileUtils;
import com.ai.module.chat.util.MrHeOpenAiService;
import com.ai.module.chat.util.aliyun.AliyunUtil;
import com.alibaba.fastjson2.JSONObject;
import com.baomidou.mybatisplus.core.toolkit.StringPool;
import com.theokanning.openai.image.CreateImageRequest;
import com.theokanning.openai.image.Image;
import io.github.asleepyfish.enums.audio.AudioResponseFormatEnum;
import io.github.asleepyfish.enums.exception.ChatGPTErrorEnum;
import io.github.asleepyfish.exception.ChatGPTException;
import io.github.asleepyfish.service.OpenAiProxyService;
import io.github.asleepyfish.util.OpenAiUtils;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.io.Resource;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;
import org.springframework.web.client.RestTemplate;
import org.springframework.web.multipart.MultipartFile;

import javax.imageio.ImageIO;
import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletResponse;
import javax.websocket.Session;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import java.io.OutputStream;
import java.nio.charset.StandardCharsets;
import java.util.*;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.stream.Collectors;
import java.util.zip.ZipEntry;
import java.util.zip.ZipOutputStream;


/**
 * @author: MrHeg
 * @create: 2023-09-01 20:37
 * @description:
 **/
@Slf4j
@Service(value = "chat4Service")
public class Chat4ServiceImpl implements ChatService {
    @Autowired
    UserImageMapper userImageMapper;

    @Autowired
    OpenAiProxyService openAiProxyService;

    @Autowired
    private MrHeOpenAiService mrHeOpenAiService;

    @Autowired
    private ChatContentMapper chatContentMapper;

    @Autowired
    private UserInfoProperty userInfoProperty;

    @Autowired
    private UserRobotService userRobotService;

    @Autowired
    private BannerRecordService bannerRecordService;

    @Autowired
    private UserImageAnalyzeService userImageAnalyzeService;


    @Override
    public List<String> talk(String message) {
        return null;
    }

    public static String ERROR_G_MESSAGE = "您的发言已违规,@若您多次违规,@将进行封号处理!!";
    public static String ERROR_MESSAGE = "您的发言已违规,@违规词汇(%s),@若您多次违规,@将进行封号处理!!";

    @Autowired
    private MemberCenterService memberCenterService;

    @Async
    public void insertUserChat(UserTimeVo userTimeVo) {
        Long cost = userTimeVo.getBeginTime() - userTimeVo.getStartTime();
        String content = userTimeVo.getChatGptTalk()
                .replaceAll("\"\"", "").replace("\\\"", "\"");
        String message = userTimeVo.getAskContent();
        String robotId = userTimeVo.getRobotId();
        String userUUidId = userTimeVo.getUser();
        ChatContentEntity chatContent = new ChatContentEntity();
        chatContent.setUserId(userUUidId);
        chatContent.setChatGpt(content);
        chatContent.setContent(message);
        chatContent.setRobotId(robotId);
        chatContent.setCostTime(cost.intValue());
        chatContent.setUuid(userTimeVo.getUuid());
        int insert = chatContentMapper.insert(chatContent);
        // 进行积分操作
        memberCenterService.dealChatUserPoints(userTimeVo);
        log.info("进行数据入库 {},insert:{}", JSONObject.toJSONString(chatContent), insert);
        // 判断是不是 新的 对话,新的对话生成 对话信息
        Boolean start = userTimeVo.getStart();
        if (start !=null && start){
            // 创建 机器人
            UserRobotEntity userRobot = new UserRobotEntity();
            if (content.length()>= 20){
                 content = content.substring(0, 20);
            }
            userRobot.setRobotName(content);
            userRobot.setUserId(userTimeVo.getUser());
            userRobot.setIsDefault(0);
            userRobot.setSourceId("default");
            userRobot.setUuid(userTimeVo.getRobotId());
            userRobotService.save(userRobot);
        }

    }

    @Override
    public String downloadImage(String desc) {
        return null;
    }

    @Override
    public void talkVue(UserTalkReq userTalkReq, HttpServletResponse response) throws IOException {
        response.setContentType("text/event-stream");
        response.setCharacterEncoding("UTF-8");
        String askMessage = userTalkReq.getMessage();

        ServletOutputStream os = response.getOutputStream();
        UserTimeVo userTimeVo = new UserTimeVo();
        userTimeVo.setAskContent(askMessage);
        userTimeVo.setRobotId(userTalkReq.getRobotId());
        userTimeVo.setStartTime(System.currentTimeMillis());
        userTimeVo.setUser(ThreadLocalContext.getUserId());
        userTimeVo.setBeginTime(System.currentTimeMillis());
        userTimeVo.setSourceId(userTalkReq.getRobotId());
        userTimeVo.setSource(PointSource.commonChat);
        // 禁用缓存
        response.setHeader("Cache-Control", "no-cache");


        RiskReason riskReason = getRiskReason(askMessage);
        Boolean success = riskReason.getSuccess();
        if (success) {
            mrHeOpenAiService.createStreamChat4(userTimeVo, os);
        } else {
            StringBuilder sb = new StringBuilder();
            String realMessage = String.format(ERROR_MESSAGE, riskReason.getRiskWords());
            for (String errorMessage : realMessage.split("@")) {
                String sseFormattedResponse = "data: " + errorMessage + "\n\n";
                os.write(sseFormattedResponse.getBytes(StandardCharsets.UTF_8));
                os.flush();
                sb.append(errorMessage);
            }
            os.write(("end" + "\n\n").getBytes(StandardCharsets.UTF_8));
            os.close();
            userTimeVo.setChatGptTalk(sb.toString());
        }
        insertUserChat(userTimeVo);

    }

    private static RiskReason getRiskReason(String askMessage) {
        return AliyunUtil.getRiskReason(askMessage);
    }


    @Override
    public List<String> createImage(String desc) {
        long start = System.currentTimeMillis();
//        String data = HttpUtil.get("https://oaidalleapiprodscus.blob.core.windows.net/private/org-Dz0nfvcnz6sFJuIOTJsKgLeS/user-GEgWGmXjIYsk89ssD35AFlN4/img-XyNiiUBGJJZZyYnJXMfI8oSv.png?st=2024-02-25T01%3A43%3A52Z&se=2024-02-25T03%3A43%3A52Z&sp=r&sv=2021-08-06&sr=b&rscd=inline&rsct=image/png&skoid=6aaadede-4fb3-4698-a8f6-684d7786b067&sktid=a48cca56-e6da-484e-a814-9c849652bcb3&skt=2024-02-24T23%3A41%3A25Z&ske=2024-02-25T23%3A41%3A25Z&sks=b&skv=2021-08-06&sig=vMOFlXvNsJZfJQYmEJDxv0Miw3UorPq0xWr3O1aMChg%3D");

        JSONObject jsonObject = MrHeOpenAiService.createImage4(desc);
        log.info("DALLA模型画图耗时[{}],返回值[{}]", System.currentTimeMillis() - start, jsonObject);
        List<LinkedHashMap> mapList = jsonObject.getJSONArray("data").toJavaList(LinkedHashMap.class);
        LinkedHashMap map = mapList.get(0);

        return Collections.singletonList((String) map.get("url"));
    }


    @Override
    public void downloadImage(String desc, HttpServletResponse response) throws Exception {
        // OpenAiUtils.downloadImage(desc, response);
        UserLoginInfo userLoginInfo = ThreadLocalContext.getUserLoginInfo();
        String userUUidId = userLoginInfo.getUuid();
        int userId = userLoginInfo.getId();
        CreateImageRequest request = MrHeOpenAiService.createImageRequest(desc);
        String realPath =
                String.format("%s/%s/%s%s", "dalla",
                        userId, DateUtils.getTransDateTime(), ".png");
        log.info("文件创建目录为[{}]", realPath);
        File file = FileUtils.createSaveFile(realPath);
        List<String> imageBase64 = openAiProxyService.createImages(request).getData().stream()
                .map(Image::getB64Json).collect(Collectors.toList());
        BufferedImage base64Image = MrHeOpenAiService.getImageFromBase64(imageBase64.get(0));
        asyncSaveImage(userUUidId, realPath, file, base64Image);
        dealDowanload(response, imageBase64);
    }

    private void dealDowanload(HttpServletResponse response, List<String> imageBase64) {
        try (OutputStream os = response.getOutputStream()) {
            if (imageBase64.size() == 1) {
                response.setContentType("image/png");
                response.setHeader("Content-Disposition", "attachment; filename=generated.png");
                BufferedImage bufferedImage = MrHeOpenAiService.getImageFromBase64(imageBase64.get(0));
                //new File()
                ImageIO.write(bufferedImage, "png", os);
            } else {
                response.setContentType("application/zip");
                response.setHeader("Content-Disposition", "attachment; filename=images.zip");
                try (ZipOutputStream zipOut = new ZipOutputStream(os)) {
                    for (int i = 0; i < imageBase64.size(); i++) {
                        BufferedImage bufferedImage = MrHeOpenAiService.getImageFromBase64(imageBase64.get(i));
                        ZipEntry zipEntry = new ZipEntry("image" + (i + 1) + ".png");
                        zipOut.putNextEntry(zipEntry);
                        ImageIO.write(bufferedImage, "png", zipOut);
                        zipOut.closeEntry();
                    }
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
            throw new ChatGPTException(ChatGPTErrorEnum.DOWNLOAD_IMAGE_ERROR);
        }
    }

    @Async("dealImageTask")
    public void asyncSaveImage(String userUUidId, String realPath, File file, BufferedImage base64Image) throws IOException {
        boolean png = ImageIO.write(base64Image, "png", file);
        if (png) {
            Long sendMessageTime = (Long) ThreadLocalContext.get(StringConstant.CURRENT_TIME);
            long currentTime = System.currentTimeMillis();
            UserImageEntity userImage = new UserImageEntity();
            userImage.setFilePath(realPath);
            userImage.setUserId(userUUidId);
            userImageMapper.insert(userImage);
        }
        log.info("图片的真实链接为: " + realPath);
    }

    @javax.annotation.Resource
    private RestTemplate restTemplate;

    @Async
    public void asyncSaveImage(String userUUidId, String realPath, Long sendMessageTime) throws IOException {
        long currentTime = System.currentTimeMillis();
        UserImageEntity userImage = new UserImageEntity();
        userImage.setFilePath(realPath);
        userImage.setUserId(userUUidId);
        userImageMapper.insert(userImage);
        log.info("图片的真实链接为: " + realPath);
    }

    @Override
    public String transferVoice(MultipartFile file) {
        return null;
    }

    @Override
    @SneakyThrows
    public String voice2Text(MultipartFile file) {
        Resource resource = file.getResource();
        File originFile = resource.getFile();
        String fileText = OpenAiUtils.transcription(originFile, AudioResponseFormatEnum.TEXT);
        return fileText;
    }

    @Override
    @SneakyThrows
    public String voice2English(MultipartFile file) {
        Resource resource = file.getResource();
        File originFile = resource.getFile();
        return OpenAiUtils.translation(originFile, AudioResponseFormatEnum.TEXT);

    }

    @Override
    public void talkMange(String message) {
        String userUUidId = ThreadLocalContext.getUserLoginInfo().getUuid();

        UserTimeVo userTimeVo = new UserTimeVo();
        userTimeVo.setAskContent(message);
        userTimeVo.setStartTime(System.currentTimeMillis());
        userTimeVo.setUser(userUUidId);
        mrHeOpenAiService.createStreamChat4(userTimeVo, System.out);
    }


    @Override
    public void talkWebSocket(UserMessage userMessage, WebSocketController webSocketController, Session session) {
        memberCenterService.checkChatPoint(userMessage.getModelType());
        UserLoginInfo userLoginInfo = ThreadLocalContext.getUserLoginInfo();
        String askMessage = userMessage.getUserMessage();
        UserTimeVo userTimeVo = new UserTimeVo();
        userTimeVo.setAskContent(askMessage);
        userTimeVo.setRobotId(userMessage.getRobotId());
        userTimeVo.setStartTime(System.currentTimeMillis());
        userTimeVo.setUser(ThreadLocalContext.getUserId());
        userTimeVo.setBeginTime(System.currentTimeMillis());
        userTimeVo.setModelType(userMessage.getModelType());
        userTimeVo.setBeforePoints(userLoginInfo.getPoints());
        userTimeVo.setIsVIP(userLoginInfo.getVip());
        userTimeVo.setLoginToken(userLoginInfo.getLoginToken());
        userTimeVo.setSourceId(userMessage.getRobotId());
        userTimeVo.setSource(PointSource.commonChat);
        userMessage.setStartChatTime(DateUtils.getCurrentTime());
        String uuid = UUID.randomUUID().toString();

        String regex = "(?i)(chatgpt|openai|gpt)";
        // 检查字符串是否匹配
        boolean containsSensitiveWords = askMessage.matches(".*" + regex + ".*");
        if (containsSensitiveWords) {
            userTimeVo.setUuid(uuid);
            // 正则表达式，用于匹配"chatgpt"或"gpt"(不区分大小写)
            // 编译正则表达式
            Pattern pattern = Pattern.compile(regex);
            Matcher matcher = pattern.matcher(askMessage);
            List<String> riskList = new ArrayList<>();
            // 循环查找匹配项
            while (matcher.find()) {
                String group = matcher.group();
                riskList.add(group);
            }
            // String realMessage = String.format(ERROR_G_MESSAGE, String.join("@",riskList));
            for (String errorMessage : ERROR_G_MESSAGE.split("@")) {
                try {
                    Thread.sleep(500);
                } catch (InterruptedException e) {
                    throw new RuntimeException(e);
                }

                userMessage.setUserMessage(errorMessage);
                webSocketController.sendMessage(session, userMessage);
            }
            userMessage.setUserMessage("");
            userMessage.setEnd(true);
            webSocketController.sendMessage(session, userMessage);
            userTimeVo.setChatGptTalk(ERROR_G_MESSAGE.replaceAll("@", ""));
            insertUserChat(userTimeVo);
            bannerRecordService.textCheck(String.join(",", riskList), uuid, askMessage, Source.TALK);
            return;
        }
        RiskReason riskReason = getRiskReason(askMessage);
        Boolean success = riskReason.getSuccess();
        if (success) {
            mrHeOpenAiService.createStreamChat4WebSocket(userTimeVo, webSocketController, session);
        } else {
            String realMessage = String.format(ERROR_MESSAGE, riskReason.getRiskWords());
            for (String errorMessage : realMessage.split("@")) {
                try {
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    throw new RuntimeException(e);
                }
                userMessage.setUserMessage(errorMessage);
                webSocketController.sendMessage(session, userMessage);
            }
            userMessage.setUserMessage(StringPool.EMPTY);
            userMessage.setEnd(true);
            webSocketController.sendMessage(session, userMessage);
            userTimeVo.setChatGptTalk(realMessage.replaceAll("@", ""));
            bannerRecordService.textCheck(String.join(",", riskReason.getRiskWords()),
                    uuid,
                    askMessage,
                    Source.TALK
            );
            //return;
        }
        userTimeVo.setUuid(uuid);
        userTimeVo.setStart(userMessage.getIsStart());
        insertUserChat(userTimeVo);
    }





    @Override
    public List<String> talkChatPic(UserTalkReq userTalkReq)  {

        String askMessage = userTalkReq.getMessage();

        UserTimeVo userTimeVo = new UserTimeVo();
        userTimeVo.setAskContent(askMessage);
        userTimeVo.setRobotId(userTalkReq.getRobotId());
        userTimeVo.setStartTime(System.currentTimeMillis());
        userTimeVo.setUser(ThreadLocalContext.getUserId());
        userTimeVo.setBeginTime(System.currentTimeMillis());
        userTimeVo.setSourceId(userTalkReq.getRobotId());
        userTimeVo.setSource(PointSource.product);
        RiskReason riskReason = getRiskReason(askMessage);

        return null;
    }

}
